package cn.topkinson.s3m4.gateway.filter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Author huangzihao
 * @Date 2020/9/9 19:22
 */
@Component
@RefreshScope
public class LoginFilter implements GlobalFilter, Ordered {

    @Value("${anti-brush.time-window}")
    private Integer time_window;
    @Value("${anti-brush.times}")
    private Integer times;

    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        System.out.println("time_window:"+time_window+"===times:"+times);
        InetSocketAddress remoteAddress = request.getRemoteAddress();
        String ip = remoteAddress.getHostString();
        String path = request.getURI().getPath();
        if (path.contains("register")){
            System.out.println("ip"+ip);
            if(antiBrush(ip)){
                return chain.filter(exchange);
            }else{
                response.setStatusCode(HttpStatus.SEE_OTHER); // 状态码
                String data = "ip["+ip+"]已在["+time_window+"]分钟内访问注册接口超过["+times+"]次，请稍后再试！";
                System.out.println(data);
                DataBuffer wrap = response.bufferFactory().wrap(data.getBytes());
                return response.writeWith(Mono.just(wrap));
            }
        }
        //白名单
        if (path.contains("user/login")||path.contains("code/create")){
            return chain.filter(exchange);
        }
        return chain.filter(exchange);
        /*HttpCookie cookie = request.getCookies().getFirst("token");
        if (cookie!=null){
            if(cookie.getValue()!=null){
                return chain.filter(exchange);
            }
        }*/
        /*response.setStatusCode(HttpStatus.UNAUTHORIZED); // 状态码
        String data = "未通过鉴权";
        System.out.println(data);
        DataBuffer wrap = response.bufferFactory().wrap(data.getBytes());
        return response.writeWith(Mono.just(wrap));*/


    }

    @Override
    public int getOrder() {
        return 0;
    }


    //防刷控制
    private boolean antiBrush(String ip){
        long nowTime = System.currentTimeMillis();
        String antiBrushKey = "antibrush:"+ip;
        //时间范围内的数量（前10秒-当前时间）
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
        if (redisTemplate.hasKey(antiBrushKey)){
            long beforeTime = nowTime - 1000 * 60 * time_window;//N分钟前
            long count = redisTemplate.opsForZSet().count(antiBrushKey, beforeTime, nowTime);
            if (count >= times){//超过预设值
                return false;
            }
        }
        redisTemplate.opsForZSet().add(antiBrushKey, nowTime+"", nowTime);//当前的请求时间，及其分值
        redisTemplate.expire(antiBrushKey,time_window, TimeUnit.MINUTES);
        return true;
    }
}
